﻿using System;
using System.Configuration;
using System.Linq;
using System.Web;
using Common.Logging;
using Newtonsoft.Json;
using OutDbContext;
using Senparc.Weixin;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.AdvancedAPIs.TemplateMessage;
using Senparc.Weixin.MP.CommonAPIs;
using User.Api.BizExtensions;

namespace User.Api.Helpers
{
    public class MessageHelper
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(MessageHelper));
        private static readonly string WxOauth2State = "GbkYin666";

        #region 模板消息参数
        const string StopRegTempalteId = "1_fankBZUYqfaIMWeruSvt82usGnf_TRqsRZPvP_N9E";

        const string HospCurriculumTempalteId = "LzPFry5piXlMhP2I19oIm3MHs6I39Ptj1OpDETf8R4E";

        const string ApptTempalteId = "FakopI_HsBPJM7XSC3Rf3XinblXx5pXbQbBoMIXOkD0";

        const string RefundTemplateId = "1w2tcJrx2bfMo4p43wMFc6R4518k2zPm_ucqc3_WZ24";

        const string DangtianTemplateId = "KlL7UwADxFpDPtWCoow_wKYHz5cQedSD28Ke71KQJpc";

        const string PayTemplateId = "SjjVaO0trZh6ngHc9OcGJv6Dw990MM67G4W7y-IaQic";

        const string FailTemplateId = "OZ11LIvPjHBrVSQ5P6Kp2WFvoFGdH05WzKRC6zac4DA ";

        const string CancelTemplateId = "5oBH0YaK6G184bgXQEc6sS3avr-NZ9OnFhce8B-YoSE";

        const string SinginTemplateId = "tdav2V-os-LlcctR6GUT-DLISYYVQKpYPTthsnKew60";

        const string TopColor = "#0000FF";

        const string FirstColor = "#173177";

        const string RemarkColor = "#173177";

        const string NoticeColor = "#173177";
        #endregion


        /// <summary>
        /// 获取网页地址
        /// </summary>
        /// <param name="routePath"></param>
        /// <returns></returns>
        public static string GetH5Url(string routePath)
        {
            var h5BaseAddress = ConfigurationManager.AppSettings["H5BaseAddress"];
            var baseAddress = ConfigurationManager.AppSettings["BaseAddress"];
            var appId = ConfigurationManager.AppSettings["WeixinAppId"];

            var url = h5BaseAddress + routePath;

            var oauth2Url = OAuthApi.GetAuthorizeUrl(appId,
                baseAddress
                + "api/Auth/WxOauth2?url="
                + HttpUtility.UrlEncode(url), WxOauth2State, OAuthScope.snsapi_userinfo);

            return oauth2Url;
        }

        /// <summary>
        /// 课程提醒通知        
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        /// 
        //public static void SendRegCurriculumMsg(int orderId, int retryCount = 0)
        //{
        //    if ((request.NoteList != null) && request.NoteList.Count > 5 || request.NoteList == null)
        //        return null;
        //    var sendData = new
        //    {
        //        touser = request.OpenId,
        //        template_id = HospCurriculumTempalteId,
        //        url = request.RedirectUrl,
        //        topcolor = TopColor,

        //        data = new
        //        {
        //            first = new
        //            {
        //                value = request.First,
        //                color = RemarkColor
        //            },
        //            keyword1 = new
        //            {
        //                value = request.NoteList[1] ?? "",
        //                color = NoticeColor
        //            },

        //            keyword2 = new
        //            {
        //                value = request.NoteList[4] ?? "",
        //                color = NoticeColor
        //            },
        //            keyword3 = new
        //            {
        //                value = request.NoteList[3] ?? "",
        //                color = NoticeColor
        //            },
        //            keyword4 = new
        //            {
        //                value = request.NoteList[2] ?? "",
        //                color = NoticeColor
        //            },

        //            remark = new
        //            {
        //                value = "点击即可报名",
        //                color = NoticeColor
        //            }
        //        }
        //    };
        //    return sendData;
        //}

        /// <summary>
        /// 发送挂号成功消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        /// <returns></returns>
        public static void SendRegSucceedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.Where(x => x.Id == orderId).
                    Select(x => new
                    {
                        x.Id,
                        x.OrderNo,
                        x.CardName,
                        x.CardNo,
                        x.DeptName,
                        x.DoctorName,
                        x.RegDate,
                        x.SumFee,
                        x.WxUserId,
                        x.StartTime,
                        x.EndTime,
                        x.OrderType
                    }).FirstOrDefault();
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;


                var url = GetH5Url("/index/reg-order-detail/" + order.Id);
                string message;
                var strHeader = "您好！";
                if (!string.IsNullOrEmpty(order.CardName))
                    strHeader = "尊敬的" + order.CardName + "(先生/女士)！";
                if (order.OrderType == "0")
                {
                    message =
                        string.Format(
                            "{0}您已经预约我院{1}医师，" +
                            "{2} {3}-{4}时段就诊;请您于{5}前到护士站报到，" +
                            "按照急危重优先和预约优先的原则，我们将安排您在预约时间内就诊，如果未报到或超过{6}报到，我们将按现场挂号时间安排就诊，敬请谅解！\r\n" +
                            "<a href='{7}'>点这里【查看挂号单】</a>",
                            strHeader,
                            order.DeptName + order.DoctorName,
                            order.RegDate,
                            order.StartTime,
                            order.EndTime,
                            order.StartTime,
                            order.EndTime,
                            url);
                }
                else
                {
                    message =
                        string.Format(
                            "{0}您已经微信当天挂号成功，请您现在尽快到{1}门诊护士站报到，" +
                            "护士将按实际报到时间安排您就诊，如果未报到，您的名字将无法进入就诊队列，" +
                            "医师将无法叫号，上午微信挂号的当天上午报到有效，下午微信挂号的当天下午报到有效，敬请谅解！\r\n" +
                            "<a href='{2}'>点这里【查看挂号单】</a>",
                            strHeader,
                            order.DeptName,url);
                }

                try
                {
                    //Logger.ErrorFormat("发送挂号成功消息时 openId 出错，信息：{0}", openId);
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送挂号成功消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendRegSucceedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送挂号成功消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送挂号失败消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendRegFailedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.Where(x => x.Id == orderId)
                    .Select(x => new
                    {
                        x.Id,
                        x.OrderNo,
                        x.CardName,
                        x.CardNo,
                        x.DeptName,
                        x.DoctorName,
                        x.RegDate,
                        x.SumFee,
                        x.WxUserId
                    }).FirstOrDefault();
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var message =
                    string.Format(
                    "挂号失败！\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "科室：{2}\r" +
                    "医生：{3}\r" +
                    "就诊日期：{4}\r" +
                    "挂号费用：{5} 元",
                    order.CardName,
                    order.CardNo,
                    order.DeptName,
                    order.DoctorName,
                    order.RegDate,
                    order.SumFee.GetValueOrDefault().ToString("F2"));

                if (order.SumFee > 0)
                {
                    message += "\r\n系统正在执行退费操作，稍后您的所缴纳的款项将会退回您的账户中";
                }

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送挂号失败消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendRegFailedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送挂号失败消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送挂号失败退费成功消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendRegFailedRefundSucceedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.Where(x => x.Id == orderId)
                .Select(x => new
                {
                    x.Id,
                    x.OrderNo,
                    x.CardName,
                    x.CardNo,
                    x.DeptName,
                    x.DoctorName,
                    x.RegDate,
                    x.SumFee,
                    x.WxUserId
                }).FirstOrDefault();
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var message =
                    string.Format(
                    "退费成功！\r" +
                    "挂号单信息：\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "科室：{2}\r" +
                    "医生：{3}\r" +
                    "就诊日期：{4}\r" +
                    "挂号费用：{5} 元\r\n" +
                    "您所缴纳的款项已退回。微信零钱支付即刻到账，银行卡支付1-3个工作日内到账。请注意查收",
                    order.CardName,
                    order.CardNo,
                    order.DeptName,
                    order.DoctorName,
                    order.RegDate,
                    order.SumFee.GetValueOrDefault().ToString("F2"));

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送挂号失败退费成功消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendRegFailedRefundSucceedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送挂号失败退费成功消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送退号成功消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendUnpickupSucceedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.Where(x => x.Id == orderId)
                .Select(x => new
                {
                    x.Id,
                    x.OrderNo,
                    x.CardName,
                    x.CardNo,
                    x.DeptName,
                    x.DoctorName,
                    x.RegDate,
                    x.SumFee,
                    x.WxUserId
                }).FirstOrDefault();
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var message =
                    string.Format(
                    "退号成功！\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "科室：{2}\r" +
                    "医生：{3}\r" +
                    "就诊日期：{4}\r" +
                    "挂号费用：{5} 元",
                    order.CardName,
                    order.CardNo,
                    order.DeptName,
                    order.DoctorName,
                    order.RegDate,
                    order.SumFee.GetValueOrDefault().ToString("F2"));

                if (order.SumFee > 0)
                {
                    message += "\r\n系统正在执行退费操作，稍后您的所缴纳的款项将会退回您的账户中";
                }

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送退号成功消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendUnpickupSucceedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送退号成功消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送退号失败消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        /// <returns></returns>
        public static void SendUnpickupFailedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.Where(x => x.Id == orderId)
                 .Select(x => new
                 {
                     x.Id,
                     x.OrderNo,
                     x.CardName,
                     x.CardNo,
                     x.DeptName,
                     x.DoctorName,
                     x.RegDate,
                     x.SumFee,
                     x.WxUserId
                 }).FirstOrDefault();
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var url = GetH5Url("/index/reg-order-detail/" + order.Id);

                var message =
                    string.Format(
                    "退号失败！\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "科室：{2}\r" +
                    "医生：{3}\r" +
                    "就诊日期：{4}\r" +
                    "挂号费用：{5} 元\r\n" +
                    "<a href='{6}'>点这里【查看挂号单】</a>",
                    order.CardName,
                    order.CardNo,
                    order.DeptName,
                    order.DoctorName,
                    order.RegDate,
                    order.SumFee.GetValueOrDefault().ToString("F2"),
                    url);

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送退号失败消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendUnpickupFailedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送退号失败消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送退号成功退费成功消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendUnpickupSucceedRefundSucceedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.Where(x => x.Id == orderId)
                .Select(x => new
                {
                    x.Id,
                    x.OrderNo,
                    x.CardName,
                    x.CardNo,
                    x.DeptName,
                    x.DoctorName,
                    x.RegDate,
                    x.SumFee,
                    x.WxUserId
                }).FirstOrDefault();
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var message =
                    string.Format(
                    "退费成功！\r" +
                    "挂号单信息：\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "科室：{2}\r" +
                    "医生：{3}\r" +
                    "就诊日期：{4}\r" +
                    "挂号费用：{5} 元\r\n" +
                    "您所缴纳的款项已退回。微信零钱支付即刻到账，银行卡支付1-3个工作日内到账。请注意查收",
                    order.CardName,
                    order.CardNo,
                    order.DeptName,
                    order.DoctorName,
                    order.RegDate,
                    order.SumFee.GetValueOrDefault().ToString("F2"));

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送退号成功退费成功消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendUnpickupSucceedRefundSucceedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送退号成功退费成功消息出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送缴费成功通知
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendBillSucceedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.BillOrder.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;

                var url = GetH5Url("/index/bill-order-detail/" + order.Id);

                var yibaoMsg = "";
                if (order.YiBaoStatus == BillOrderExtensions.YiBaoStatus.使用了医保.ToInt32()
                    && !string.IsNullOrEmpty(order.YiBaoJydjh))
                {
                    yibaoMsg = string.Format(
                        "个人支付：{0} 元\r" +
                        "医保支付：{1} 元\r",
                        order.PersonalMoney.GetValueOrDefault().ToString("F2"),
                        order.YibaoMoney.GetValueOrDefault().ToString("F2")
                        );
                }

                var message =
                    string.Format(
                    "缴费成功！\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "就诊流水号：{2}\r" +
                    "开单时间：{3}\r" +
                    "开单科室：{4}\r" +
                    yibaoMsg +
                    "总费用：{5} 元\r\n" +
                    "<a href='{6}'>点这里【查看缴费单】</a>"
                    + "\r\n 如需补打发票，请于当天移步人工窗口办理，过期无效。",
                    order.CardName,
                    order.CardNo,
                    order.ClinicNo,
                    order.OrderDate,
                    order.OrderDept,
                    order.PrescMoney.GetValueOrDefault().ToString("F2"),
                    url);

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送缴费成功消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendBillSucceedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送缴费成功消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送缴费失败通知
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendBillFailedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.BillOrder.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var message =
                    string.Format(
                    "缴费失败！\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "就诊流水号：{2}\r" +
                    "开单时间：{3}\r" +
                    "开单科室：{4}\r" +
                    "总费用：{5} 元\r",
                    order.CardName,
                    order.CardNo,
                    order.ClinicNo,
                    order.OrderDate,
                    order.OrderDept,
                    order.PrescMoney.GetValueOrDefault().ToString("F2"));

                message += "\r\n系统正在执行退费操作，稍后您的所缴纳的款项将会退回您的账户中";

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送缴费失败消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendBillFailedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送缴费失败消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }

        /// <summary>
        /// 发送缴费失败退费成功消息
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendBillFailedRefundSucceedMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.BillOrder.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return;
                }
                var user = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (user == null)
                {
                    return;
                }
                string openId = user.OpenId;
                var message =
                    string.Format(
                    "退费成功！\r" +
                    "缴费单信息：\r" +
                    "订单号：" + order.OrderNo + "\r" +
                    "姓名：{0}\r" +
                    "卡号：{1}\r" +
                    "就诊流水号：{2}\r" +
                    "开单时间：{3}\r" +
                    "开单科室：{4}\r" +
                    "总费用：{5} 元\r\n" +
                    "您所缴纳的款项已退回。微信零钱支付即刻到账，银行卡支付7个工作日内到账。请注意查收",
                    order.CardName,
                    order.CardNo,
                    order.ClinicNo,
                    order.OrderDate,
                    order.OrderDept,
                    order.PrescMoney.GetValueOrDefault().ToString("F2"));

                try
                {
                    CustomApi.SendText(null, openId, message);
                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送缴费失败退费成功消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendBillFailedRefundSucceedMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送缴费失败退费成功消息时出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }


        /// <summary>
        /// 发送停诊通知
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="retryCount"></param>
        public static void SendHaltMsg(int orderId, int retryCount = 0)
        {
            using (var ctx = new HzfyWeiXinEntities())
            {
                var order = ctx.ApptOrder.FirstOrDefault(x => x.Id == orderId);
                if (order == null)
                {
                    return;
                }
                var userobj = ctx.WxUser.FirstOrDefault(x => x.Id == order.WxUserId);
                if (userobj == null)
                {
                    return;
                }
                var url = "";// GetH5Url("/index/reg-order-detail/" + order.Id);
              
                var data = new
                {
                    first = new
                    {
                        value = "您预约的医生停诊，系统正在执行退费操作，稍后您的所缴纳的款项将会退回您的账户中",
                        color = "#173177"
                    },
                    hospitalname = new
                    {
                        value = "惠州第一妇幼保健院",
                        color = "#173177"
                    },

                    deptname = new
                    {
                        value = order.DeptName ?? "",
                        color = "#173177"
                    },
                    doctorname = new
                    {
                        value = order.DoctorName ?? "普通号",
                        color = "#173177"
                    },
                    planstarttime = new
                    {
                        value = (order.RegDate + (order.OrderType == "2" ? order.StartTime + "-" + order.EndTime : order.StartTime)) ?? "",
                        color = "#173177"
                    },
                    remark = new
                    {
                        value = "请您尽快预约其他医生。",
                        color = "#173177"
                    }
                };

                try
                {
                    var result = SendTemplateMessage(orderId, "停诊通知", null, userobj.OpenId, StopRegTempalteId, TopColor, "", data);

                }
                catch (ErrorJsonResultException ex)
                {
                    Logger.ErrorFormat("发送停诊消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                    if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                    {
                        var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                        AccessTokenContainer.GetAccessTokenResult(appId, true);

                        if (retryCount <= 1)
                        {
                            retryCount++;
                            SendHaltMsg(orderId, retryCount);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.ErrorFormat("发送停诊消息出错，信息：{0}", JsonConvert.SerializeObject(ex));
                }
            }
        }


        /// <summary>
        /// 发送预约报到通知
        /// </summary>
        /// <param name="endTime"></param>
        /// <param name="retryCount">重复次数</param>
        /// <param name="openId"></param>
        /// <param name="deptName"></param>
        /// <param name="doctorName"></param>
        /// <param name="regDate"></param>
        /// <param name="startTime"></param>
        public static bool SendSinginMsg(string openId, string deptName, string doctorName, string regDate,
            string startTime, string endTime, int retryCount = 0)
        {
            var sendResult = false;
            var data = new
            {
                first = new
                {
                    value = "您预约的订单:",
                    color = FirstColor
                },

                keyword1 = new //科室
                {
                    value = deptName,
                    color = NoticeColor
                },

                keyword2 = new //医生
                {
                    value = doctorName,
                    color = NoticeColor
                },

                keyword3 = new //日期
                {
                    value = regDate,
                    color = NoticeColor
                },

                keyword4 = new //时间
                {
                    value = startTime + "-" + endTime,
                    color = NoticeColor
                },

                remark = new
                {
                    value = "请您于" + startTime + "前到达我院（现场护士站）进行" + deptName + "预约报到，并做好相关就诊准备，我们将竭诚为您服务！",
                    color = RemarkColor
                }
            };

            try
            {
                var result = TemplateApi.SendTemplateMessage(null, openId, SinginTemplateId, TopColor, "", data);
                sendResult = result.errcode == ReturnCode.请求成功;
            }
            catch (ErrorJsonResultException ex)
            {
                Logger.ErrorFormat("发送预约报到消息时 Separc Weixin SDK 出错，信息：{0}", JsonConvert.SerializeObject(ex));

                if (ex.JsonResult.errcode == ReturnCode.获取access_token时AppSecret错误或者access_token无效
                    || ex.JsonResult.errcode == ReturnCode.不合法的access_token)
                {
                    var appId = AccessTokenContainer.GetFirstOrDefaultAppId();
                    AccessTokenContainer.GetAccessTokenResult(appId, true);

                    if (retryCount <= 1)
                    {
                        retryCount++;
                        SendSinginMsg(openId, deptName, doctorName, regDate, startTime, endTime, retryCount);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("发送预约报道消息出错，信息：{0}", JsonConvert.SerializeObject(ex));
            }

            return sendResult;
        }

        public static SendTemplateMessageResult SendTemplateMessage(int orderId,string sendContent, string accessTokenOrAppId, string openId, string templateId, string topcolor, string url, object data, int timeOut = 10000)
        {
            var result = TemplateApi.SendTemplateMessage(null, openId, templateId, TopColor, url, data);
            try
            {
                using (var msgctx = new HzfyWeiXinEntities())
                {
                    var msglog = new MsgNotifyRecord()
                    {
                        Destination = sendContent,
                        SendContent = sendContent,
                        //OpenId = openId,
                        //OrderId = orderId,
                        ReturnMessage = result.errcode.ToStringOrDefault(),
                        SendTime = DateTime.Now,
                        //TemplateId = templateId,
                        //url = "",
                    };
                    msgctx.MsgNotifyRecord.Add(msglog);
                    msgctx.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("保存MsgNotifyRecord出错，信息：{0}", JsonConvert.SerializeObject(ex));
            }
            return result;
        }
    }
}